package org.springframework.aop.framework.autoproxy;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

import javax.annotation.PostConstruct;

public class A17_1_1 {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean(ConfigurationClassPostProcessor.class); //解析注解@Configuration、@Bean
        context.registerBean(Config.class);
        context.refresh();
    }

    static class Config{

        @Bean
        public AnnotationAwareAspectJAutoProxyCreator creator(){
            return new AnnotationAwareAspectJAutoProxyCreator();
        }

        //解析@Autowired
        @Bean
        public AutowiredAnnotationBeanPostProcessor p1(){
            return new AutowiredAnnotationBeanPostProcessor();
        }

        //解析@PostConstruct等注解
        @Bean
        public CommonAnnotationBeanPostProcessor p2(){
            return new CommonAnnotationBeanPostProcessor();
        }

        @Bean
        public Advisor advisor(MethodInterceptor methodInterceptor){
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression("execution(* foo())");
            return new DefaultPointcutAdvisor(pointcut, methodInterceptor);
        }

        @Bean
        public MethodInterceptor methodInterceptor(){
            return new MethodInterceptor() {
                @Override
                public Object invoke(MethodInvocation invocation) throws Throwable {
                    System.out.println("before...");
                    Object result = invocation.proceed();
                    return result;
                }
            };
        }

        @Bean
        public Bean1 bean1(){
            return new Bean1();
        }

        @Bean
        public Bean2 bean2(){
            return new Bean2();
        }
    }

    static class Bean1{



        public Bean1(){
            System.out.println("Bean1 构造函数");
        }

        public void foo(){
            System.out.println("foo...");
        }

        @Autowired
        public void bean2(Bean2 bean2){
            System.out.println("bean2→bean1： bean2类型：" + bean2.getClass());
        }

        @PostConstruct
        public void init(){
            System.out.println("bean1 init.....");
        }
    }

    static class Bean2{
        public Bean2(){
            System.out.println("Bean2 构造函数");
        }



        @Autowired
        public void bean1(Bean1 bean1){
            System.out.println("bean1→bean2： bean1类型：" + bean1.getClass());
        }

        @PostConstruct
        public void init(){
            System.out.println("bean2 init.....");
        }
    }
}
